using System;
using System.Diagnostics;

namespace Needle.Utils.Parser
{
    /// <summary></summary>
    [Serializable]
    [DebuggerDisplay("[{Line},{Column}] Token {Type}: {Value}")]
    public class StringToken : IEquatable<StringToken>
    {

        /// <summary>
        /// Initializes a new instance of the Token class.
        /// </summary>
        public StringToken(string value, TokenType type)
            : this(value, type, -1, -1, -1)
        { }

        /// <summary>
        /// Initializes a new instance of the Token class.
        /// </summary>
        public StringToken(string value, TokenType type, int line, int column, int index)
        {
            _Value = value;
            _Line = line;
            _Type = type;
            _Column = column;
            _Index = index;
        }

        private readonly string _Value;
        /// <summary>
        /// The string value of the token.
        /// </summary>
        public string Value
        {
            get { return _Value; }
        }

        private readonly TokenType _Type;
        /// <summary>
        /// The type of token.
        /// </summary>
        public TokenType Type
        {
            get { return _Type; }
        }

        private readonly int _Line;
        /// <summary>
        /// The line at which the token is found
        /// </summary>
        public int Line
        {
            get { return _Line; }
        }

        private readonly int _Column;
        /// <summary>
        /// The start column of the token.
        /// </summary>
        public int Column
        {
            get { return _Column; }
        }

        private readonly int _Index;
        /// <summary>
        /// the character index in the char stream of the token.
        /// </summary>
        public int Index
        {
            get { return _Index; }
        }
        /// <summary>
        /// Debug display value
        /// </summary>
        public override string ToString()
        {
            return String.Format("[{2,4},{3,3}] {0,-12}: \'{1}\'", _Type, _Value, _Line, _Column);
        }

        private object _UserState;
        /// <summary>
        /// User data
        /// </summary>
        public object UserState
        {
            get { return _UserState; }
            set { _UserState = value; }
        }

        #region IEquatable<Token> Members

        /// <summary>
        /// returns true if the value and type of the token are the same
        /// </summary>
        public bool Equals(StringToken other)
        {
            if (Object.ReferenceEquals(other, null))
                return false;
            return this._Value == other.Value
                && this._Type == other.Type;
        }
        /// <summary>
        /// returns true if the value is of type Token and the value and TokenType are equal.
        /// </summary>
        public override bool Equals(object obj)
        {
            return ((IEquatable<StringToken>)this).Equals(obj as StringToken);
        }
        /// <summary>
        /// returns the hascode of the token.
        /// </summary>
        public override int GetHashCode()
        {
            int hashCode = _Value.GetHashCode();
            hashCode ^= ((int)_Type) << 22;
            return hashCode;
        }

        #endregion
    }
}
